public with sharing class Cald_ApproversConfigurationVF
{
	public Callidus_Configuration__c[] configurationList = null; //stores the Approvers list
    public List<Callidus_Configuration__c> displayApproverDetails {get; set;}
    public List<Callidus_Configuration__c> displayDispApproverDetails {get; set;}
    public Boolean remAppFlag {get; set;}//Flag for Remove Approver button
    public Boolean remDispAppFlag {get; set;}//Flag for Remove Approver button
    public Integer displayXRows {get; set;}//except final approver, display all rows in the first table
    public Integer displayDispXRows {get; set;}//except final approver, display all rows in the first table
    
    private List<SelectOption> usersOptionList = new List<SelectOption>();
    
    String user = 'select';//SelectList variable
    String disputeUser = 'select';
    
    private Callidus_Configuration__c con = null;
    private Boolean saveStatus {get; set;}
    private Integer approverCount {get; set;}
    private List<SelectOption> availableStageNamesList {get; set;}
    private List<SelectOption> selectedStageNamesList {get; set;}
    public String[] leftSelectList {get; set;}   
    public String[] rightSelectList {get; set;}   
    public Callidus_Dispute_Reasons__c cdr {get; set;}
    public Callidus_Dispute_Reasons__c[] cdrList {get; set;}
    public Integer cdrCount {get; set;}
    public String activeInactiveId {get; set;}
    
    String[] approverLevelList = new String[]{'Manager', 'Second Level Manager', 'Third Level Manager', 'Fourth Level Manager', 'Fifth Level Manager', 'Sixth Level Manager', 'Seventh Level Manager', 'Eigth Level Manager', 'Ninth Level Manager', 'Tenth Level Manager', 'Eleventh Level Manager', 'Twelfth Level Manager', 'Thirteenth Level Manager', 'Fourteenth Level Manager', 'Fifteenth Level Manager','Final Approver'}; 
    String[] approverLabelList = new String[]{'Approver 1', 'Approver 2', 'Approver 3', 'Approver 4', 'Approver 5', 'Approver 6', 'Approver 7', 'Approver 8', 'Approver 9', 'Approver 10', 'Approver 11', 'Approver 12', 'Approver 13', 'Approver 14', 'Approver 15', 'Final Approver'};
    private Map<Integer, String> disputeApproversLabelMap = null;
    private Map<Integer, String> disputeApproversLevelMap = null;
    
    public Cald_ApproversConfigurationVF()
    {
        configurationList = new List<Callidus_Configuration__c>();
        displayApproverDetails = new List<Callidus_Configuration__c>();
        getUsers();
        for(Callidus_Configuration__c[] cList: [select Id, Approver__c, Approver_Level__c, Response_Window__c, IsFinalApprover__c from Callidus_Configuration__c where Is_Dispute__c = false])
            for(Callidus_Configuration__c c: cList)
                configurationList.add(c);
                
        approverCount = 1;
        remDispAppFlag = remAppFlag = true;//initially Remove Approver button is disabled
        //if no approvers were saved earlier
        if(configurationList.size() == 0)
        {
            getInitialDisplayDetails();
        }
        else
        {
            saveStatus = true;
            approverCount = configurationList.size() - 1;
            if(approverCount > 1)
                remAppFlag = false;
            
            displayApproverDetails = configurationList;
        }
        
        displayXRows = displayApproverDetails.size() - 1;
        setUser(displayApproverDetails[displayXRows].Approver_Level__c);
        
        //Start: Code to retrieve Opportunity Stage Names
  		Cald_Compensable_Opportunity_Stages__c[] ccosList = [select id, Opportunity_Stage_Label__c, Opportunity_Stage_Value__c from Cald_Compensable_Opportunity_Stages__c];
		Map<String, String> ccosMap = new Map<String, String>();
        selectedStageNamesList = new List<SelectOption>();
        rightSelectList = new String[]{};
    	for(Cald_Compensable_Opportunity_Stages__c ccos: ccosList)
    	{
    		ccosMap.put(ccos.opportunity_Stage_label__c, ccos.opportunity_Stage_label__c);
    		selectedStageNamesList.add(new SelectOption(ccos.opportunity_Stage_label__c, ccos.opportunity_Stage_label__c));
    		//rightSelectList.add(ccos.opportunity_Stage_label__c);
    	}
        
        Schema.DescribeFieldResult oPL = Opportunity.StageName.getDescribe();
        List<Schema.PicklistEntry> pLVals = oPL.getPicklistValues();
        List<SelectOption> options = new List<SelectOption>();
        leftSelectList = new String[]{};
        for(Schema.PicklistEntry s: pLVals)
        {
       		if(ccosMap.get(s.getLabel()) == null)
       		{	
        		options.add(new SelectOption(s.getLabel(), s.getLabel()));
        		//leftSelectList.add(s.getLabel());
       		}
        }
        availableStageNamesList = options;
        //End: Code to retrieve Opportunity Stage Names
        
        //Start: Code for Dispute Reasons
        cdrList = [select Id, Name, Description__c, Status__c, Code_Number__c from Callidus_Dispute_Reasons__c];
        cdrCount = [select count() from Callidus_Dispute_Reasons__c];
        //End: Code for Dispute Reasons
        
        
        //Start: Code for Configure Dispute Approvers
        disputeApproversLabelMap = new Map<Integer, String>();
        Integer position = 1;
        for(String s: approverLabelList)
        {
        	disputeApproversLabelMap.put(position, s);
        	position++;
        }//end of for(String s: approverLabelList)
        
        disputeApproversLevelMap = new Map<Integer, String>();
        position = 1;
        for(String s: approverLevelList)
        {
        	disputeApproversLevelMap.put(position, s);
        	position++;
        }//end of for(String s: approverLabelList)
        
        displayDispApproverDetails = [select Id, Approver__c, Approver_Level__c, Response_Window__c, IsFinalApprover__c, Dispute_Number__c from Callidus_Configuration__c where Is_Dispute__c = true and Dispute_Number__c != 0 order by Dispute_Number__c];
        if(displayDispApproverDetails.size() == 0)//if no dispute approvers are configured yet
        {
        	Callidus_Configuration__c c = new Callidus_Configuration__c(Approver__c = 'Approver 1', Approver_Level__c = 'Manager', Response_Window__c = 5, IsFinalApprover__c = 'No', IS_Dispute__c = true, Dispute_Number__c = 1);
        	displayDispApproverDetails.add(c);
	       	c = new Callidus_Configuration__c(Approver__c = 'Final Approver', Approver_Level__c = 'select', Response_Window__c = 0, IsFinalApprover__c = 'Yes', Is_Dispute__c = true, Dispute_Number__c = 16);  
    		displayDispApproverDetails.add(c);    	
        }//end of if(displayDispApproverDetails.size() == 0)

        displayDispXRows = displayDispApproverDetails.size() - 1;
        if(displayDispApproverDetails.size() > 2)
        	remDispAppFlag = false;
        	
        setDisputeUser(displayDispApproverDetails[displayDispXRows].Approver_Level__c);

        //End: Code for Configure Dispute Approvers 
    }
    
    private List<SelectOption> getUsers()
    {
        usersOptionList.add(new SelectOption('select','Select'));

        for(User[] userList : [select Id, Name from User where IsActive = true])
        {
            for(User user: userList)
            {
                if(usersOptionList.size() <= 1000)
                {
                    usersOptionList.add(new SelectOption(user.Id, user.Name));
                }
                else
                    break;
            }
        }
        return usersOptionList;
    } 
    
    public List<SelectOption> getUserList()
    {
        return usersOptionList;
    }
    
    public List<SelectOption> getDisputeUserList()
    {
        return usersOptionList;
    }

    public String getUser()
    {
        return user;
    }
    
    public void setUser(String user) 
    {
        this.user = user;
    }   

    public String getDisputeUser()
    {
        return disputeUser;
    }

    public void setDisputeUser(String user) 
    {
        this.disputeUser = user;
    }   
    
    private String getInitialDisplayDetails()
    {
        con = new Callidus_Configuration__c(Approver__c = approverLabelList[0], Approver_Level__c = approverLevelList[0], Response_Window__c = 5, IsFinalApprover__c = 'No');
        displayApproverDetails.add(con);
        con = new Callidus_Configuration__c(Approver__c =  approverLabelList[approverLevelList.size() - 1], Approver_Level__c = 'select', Response_Window__c = 0, IsFinalApprover__c = 'Yes');
        displayApproverDetails.add(con);
        return 'success';
    }
    
    //adds new row to the table
    public PageReference addDisputeApprover()
    {
        if(displayDispApproverDetails.size() < 16)
        {
            con = new Callidus_Configuration__c(Approver__c = disputeApproversLabelMap.get(displayDispApproverDetails.size()), Approver_Level__c = disputeApproversLevelMap.get(displayDispApproverDetails.size()), Response_Window__c = 5, IsFinalApprover__c = 'No', IS_Dispute__c = true, Dispute_Number__c = displayDispApproverDetails.size());
            displayDispApproverDetails.add(displayDispApproverDetails.size() - 1, con);
            if(displayDispApproverDetails.size() == 3)
                remDispAppFlag = !remDispAppFlag;
            displayDispXRows = displayDispApproverDetails.size() - 1;
        }
        return null;
    }
    
    public PageReference removeDisputeApprover()
    {
        
        if(displayDispApproverDetails.size() > 2)
        {
            displayDispApproverDetails.remove(displayDispApproverDetails.size() - 2);
            displayDispXRows = displayDispApproverDetails.size() - 1;
            if(displayDispApproverDetails.size() == 2)
                remDispAppFlag = !remDispAppFlag;
        }
        return null;
    }
    
    //adds new row to the table
    public PageReference addApprover()
    {
        if(approverCount < 15)
        {
            con = new Callidus_Configuration__c(Approver__c = approverLabelList[approverCount], Approver_Level__c = approverLevelList[approverCount], Response_Window__c = 5, IsFinalApprover__c = 'No');
            displayApproverDetails.add(displayApproverDetails.size() -1, con);
            approverCount++;
            if(approverCount == 2)
                remAppFlag = !remAppFlag;
            displayXRows = displayApproverDetails.size() - 1;
        }
        return null;
    }
    
    public PageReference removeApprover()
    {
        
        if(approverCount > 1)
        {
            displayApproverDetails.remove(displayApproverDetails.size() - 2);
            approverCount--;
            displayXRows = displayApproverDetails.size() - 1;
            if(approverCount == 1)
                remAppFlag = !remAppFlag;
        }
        return null;
    }
    
    public PageReference saveApproverConfiguration()
    {
        try
        {
            Callidus_Configuration__c[] configList = [select id from Callidus_Configuration__c where Is_Dispute__c = false];
            //delete existing Approvers.
            if(configList.size() > 0)
                delete configList;
            
            //update Final Approver record with the current selected value.    
            displayApproverDetails[displayXRows].Approver_Level__c = user;
            
            if(displayApproverDetails[displayXRows].Approver_Level__c == 'select')
                displayApproverDetails[displayXRows].Response_Window__c = 0;
                
            ApexPages.Message msg = new ApexPages.Message(ApexPages.severity.info, 'Approvers saved successfully.');            
    
            if(saveStatus == null)
            {
                saveStatus = false;
                insert displayApproverDetails;
            }
            
            if(saveStatus)
            {
                Callidus_Configuration__c[] newConfigList = new List<Callidus_Configuration__c>();
                Callidus_Configuration__c con = null;
                for(Callidus_Configuration__c oldConfig: displayApproverDetails)
                {
                    con = new Callidus_Configuration__c(Approver__c = oldConfig.Approver__c, Approver_Level__c = oldConfig.Approver_Level__c, Response_Window__c = oldConfig.Response_Window__c, IsFinalApprover__c = oldConfig.IsFinalApprover__c);
                    newConfigList.add(con);        
                }
                if(newConfigList.size() > 0)
                    insert newConfigList;
            }
            ApexPages.addMessage(msg);
            saveStatus = true;
        }
        catch(Exception e){ApexPages.addMessages(e);}
        return null;
    }

    public PageReference saveDispApproverConfiguration()
    {
        try
        {
            Callidus_Configuration__c[] configList = [select id from Callidus_Configuration__c where Is_Dispute__c = true];
            //delete existing Approvers.
            if(configList.size() > 0)
                delete configList;
            
            //update Final Approver record with the current selected value.    
            displayDispApproverDetails[displayDispXRows].Approver_Level__c = disputeUser;
            
            if(displayDispApproverDetails[displayDispXRows].Approver_Level__c == 'select')
                displayDispApproverDetails[displayDispXRows].Response_Window__c = 0;
                
            ApexPages.Message msg = new ApexPages.Message(ApexPages.severity.info, 'Approvers saved successfully.'+displayDispApproverDetails);            
			insert displayDispApproverDetails;
			
			Callidus_Configuration__c[] dupConfigList = displayDispApproverDetails.deepClone();
			displayDispApproverDetails.clear();
			Callidus_Configuration__c cObj = null;
			for(Callidus_Configuration__c c: dupConfigList)
			{
				cObj = new Callidus_Configuration__c(Approver__c = c.Approver__c, Approver_Level__c = c.Approver_Level__c, Response_Window__c = c.Response_Window__c, IsFinalApprover__c = c.IsFinalApprover__c, Is_Dispute__c = c.Is_Dispute__c, Dispute_Number__c = c.Dispute_Number__c);
				displayDispApproverDetails.add(cObj);					
			}
			    
        }
        catch(Exception e){ApexPages.addMessages(e);}
        return null;
    }
    

    
    public List<SelectOption> getAvailableOppStageNames()
    {
    	return availableStageNamesList;
    }//end of getoppStageNames()

    public List<SelectOption> getSelectedOppStageNames()
    {
    	return selectedStageNamesList;
    }//end of getoppStageNames()
    
    public PageReference addOppStageName()
    {
    	try
    	{
    		Integer remElem = 0;
	    	for(String s: leftSelectList)
	    	{
		    	for(SelectOption so: availableStageNamesList)
		    	{
		    		if(so.getLabel() == s)
		    		{
		    			rightSelectList.add(s);
		    			selectedStageNamesList.add(new Selectoption(so.getLabel(), so.getLabel()));
		    		}
		    	}
	    	}

			Integer remCount = 0;
	    	for(String s: leftSelectList)
	    	{
	    		remCount = 0;
		    	for(SelectOption so: availableStageNamesList)
		    	{
		    		if(so.getLabel() == s)
		    		{
		    			availableStageNamesList.remove(remCount);
		    			break;
		    		}
		    		remCount++;
		    	}
	    	}
    	}
    	catch(Exception e)
    	{
    		ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, e.getMessage()));
    	}
    	return null;
    }
    
    public PageReference removeOppStageName()
    {
    	try
    	{
    		Integer remElem = 0;
	    	for(String s: rightSelectList)
	    	{
		    	for(SelectOption so: selectedStageNamesList)
		    	{
		    		if(so.getLabel() == s)
		    		{
		    			leftSelectList.add(s);
		    			availableStageNamesList.add(new Selectoption(so.getLabel(), so.getLabel()));
		    		}
		    	}
	    	}

			Integer remCount = 0;
	    	for(String s: rightSelectList)
	    	{
	    		remCount = 0;
		    	for(SelectOption so: selectedStageNamesList)
		    	{
		    		if(so.getLabel() == s)
		    		{
		    			selectedStageNamesList.remove(remCount);
		    			break;
		    		}
		    		remCount++;
		    	}
	    	}

    	}
    	catch(Exception e)
    	{
    		ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, e.getMessage()));
    	}
    	return null;
    }

    public PageReference saveOppStages()
    {
    	try
    	{
    		Cald_Compensable_Opportunity_Stages__c[] oldCCOSList = [select id from Cald_Compensable_Opportunity_Stages__c];
    		Cald_Compensable_Opportunity_Stages__c[] newCCOSList = new Cald_Compensable_Opportunity_Stages__c[]{};
    		Cald_Compensable_Opportunity_Stages__c newCCOS = null;
    		for(SelectOption so: selectedStageNamesList)
    		{
    			newCCOS = new Cald_Compensable_Opportunity_Stages__c(Opportunity_Stage_Label__c = so.getLabel(), Opportunity_Stage_Value__c = so.getValue());
    			newCCOSList.add(newCCOS);
    		}
			insert newCCOSList;
			delete oldCCOSList;
    	}
    	catch(Exception e)
    	{
    		ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.info, e.getMessage()));
    	}
        ApexPages.Message msg = new ApexPages.Message(ApexPages.severity.info, 'Stages saved successfully.');            
    	return null;
    }

	public PageReference addDisputeCode()
	{
		cdrCount++;
		cdr = new Callidus_Dispute_Reasons__c(Description__c = '', Status__c = 'Active', Code_Number__c = String.valueOf(cdrCount));
		cdrList.add(cdr);
		return null;	
	}
	
	public PageReference activeOrInactive()
	{
		for(Callidus_Dispute_Reasons__c cdr: cdrList)
		{
			if(cdr.Code_Number__c == activeInactiveId)
				if(cdr.Status__c == 'Active')
					cdr.Status__c = 'InActive';
				else
					cdr.Status__c = 'Active';
		}
		return null;	
	}
	
    public PageReference saveDisputeCode()
	{
		List<Callidus_Dispute_Reasons__c> oldCdrList = new List<Callidus_Dispute_Reasons__c>();
		List<Callidus_Dispute_Reasons__c> newCdrList = new List<Callidus_Dispute_Reasons__c>();
		
		for(Callidus_Dispute_Reasons__c cdr: cdrList)
		{
			if(cdr.Name != null)
				oldCdrList.add(cdr);
			else
				newCdrList.add(cdr);
		}
		if(oldCdrList.size() > 0)
			update oldCdrList;
		if(newCdrList.size() > 0)
			insert newCdrList;
		return null;	
	}
	
    static testMethod void testCallidus_ApproversConfigurationVF()
    {
        PageReference pg = Page.Cald_Approvers_Configuration;
        Cald_ApproversConfigurationVF ac = new Cald_ApproversConfigurationVF();
        try
        {
	        Test.startTest();
	        system.assertEquals('success', ac.getInitialDisplayDetails());
	        
	        List<SelectOption> options = new List<SelectOption>();
	        options.add(new SelectOption('select','Select'));
	
	        for(User[] userList : [select Id, Name from User where IsActive = true limit 1])
	        {
	            for(User user: userList)
	            {
	                if(options.size() <= 1000)
	                {
	                    options.add(new SelectOption(user.Id, user.Name));
	                }
	                else
	                    break;
	            }
	        }

	        system.assertEquals(options.get(0).getValue(), ac.getUserList().get(0).getValue());
	        
	        system.assertEquals(ac.displayApproverDetails[ac.displayXRows].Approver_Level__c, ac.getUser());

	        system.assertEquals(null, ac.addApprover());
	        system.assertEquals(null, ac.saveApproverConfiguration());
	        system.assertEquals(null, ac.removeApprover());
	        
	    	ac.getUserList();
	    	ac.activeOrInactive();
	    	ac.addDisputeApprover();
	    	ac.addDisputeCode();
	    	ac.getDisputeUser();
	    	ac.getDisputeUserList();
	    	ac.addOppStageName();
	    	ac.getAvailableOppStageNames();
	    	ac.getSelectedOppStageNames();
	    	ac.setUser('Test');
	    	ac.setDisputeUser('Test');
	    	ac.saveOppStages();
	    	ac.saveDisputeCode();
	    	ac.saveDispApproverConfiguration();    
	    	ac.removeDisputeApprover();
	        ac.removeOppStageName();
	        Test.stopTest();
        }
        catch(Exception e)
        {
        }       
        
    }
    
}//end of class